#!/usr/bin/perl
use strict;
use warnings;

use lib 'data/lib';
use Cwd;
use Getopt::Euclid;
use File::Copy qw( copy );
use File::Copy::Recursive qw( dircopy );
use File::Path qw( remove_tree make_path );
use Archive::Extract;

=head1 NAME

Forge - the Pawns-in-Space build system

=head1 VERSION

Version 1.0

=head1 USAGE

Forge.pl [options]

=head1 OPTIONAL ARGUMENTS

=over

=item  -t[arget] <target>

Specify build target:

=over

=item all [default] - runs all targets

=item clean - removes existing build

=item res - copies core program resources and platform-independent libraries

=item core - copies core program

=item extlib - compiles platform-dependent libraries

=back

=for Euclid:
   target.type: string
   target.default: 'all'

=item --version

=item --usage

=item --help

=item --man

=back

=head1 AUTHOR

Michael J. Lewis, C<< <mjlewis at ualberta.net> >>

=head1 LICENSE AND COPYRIGHT

Copyright 2012 Michael J. Lewis.

This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.

=cut

my $arch = $^O;
my $cwd = getcwd;

my $build_dir = 'build';
my $dist_dir = "$build_dir/dist";
my $temp_dir = "$build_dir/temp";

my $core_program = 'Pawns-in-Space.pl';
my $data = 'data';
my $extlib_source = "$data/extlib";
my @resources_to_copy = (
    'gamepieces',
    'lib',
    'gif',
    'rulesets',
);

my $target = $ARGV{'-target'};
$target = 'all' if ( !defined $target );  # Euclid default isn't working
$target =~ tr/A-Z/a-z/;

my %dispatch = (
    'clean' => \&clean,
    'res' => \&copy_resources,
    'core' => \&copy_core,
    'extlib' => \&build_extlibs,
    'all' => \&full_build,
);

if ( !defined $dispatch{$target} ) {
    print "Target [$target] is not valid.  Please run ./forge --help for"
        . " a list of supported targets.\n";
    exit;
}

print "Target: $target\n";

if ( $target ne 'clean' || $target ne 'all' ) {
    make_build_tree();
}
$dispatch{$target}->();

print "All done.  Have a nice day.\n";

sub clean {
    if ( -e $build_dir ) {
        print "Removing old $build_dir directory...\n";
        remove_tree( $build_dir,
                     { 'verbose' => 0, 'error' => \my $err } );
        die "Error in clean: @$err" if ( @$err );
    }
}

sub make_build_tree {
    make_path( $temp_dir, "$dist_dir/$data",
           { 'verbose' => 0, 'error' => \my $err } );
    die "Error in make_tree: @$err" if ( @$err );
}

sub full_build {
    print "Starting a new software build...\n";
    clean();
    make_build_tree();
    copy_resources();
    copy_core();
    build_extlibs();
}

sub copy_resources {
    print 'Copying resources';

    foreach my $resource ( @resources_to_copy ) {
        print '.';
        dircopy( "$data/$resource",
                 "$dist_dir/$data/$resource" )
            or die "Error in copy_resources (dircopy): $!";
    }
    print "\n";
}

sub copy_core {
    print "Copying core program...\n";
    copy( $core_program, $dist_dir )
        or die "Error in copy_core: $!";
}

sub build_extlibs {
    print "Building external libraries...\n";

    my $prefix_dir = "$cwd/build/dist/$data";
    my $lib_dir = "$prefix_dir/lib";

    # Read extlib contents
    opendir my $dh, $extlib_source
        or die "Error in build_extlibs: Can't open"
            . " directory $extlib_source: $!";

    my @files = grep m{\.tar\.gz}x, readdir( $dh );
    
    closedir $dh
        or die "Error in build_extlibs: Can't close"
            . " directory $extlib_source: $!\n";

    # Extract all extlib tarballs to templib
    foreach ( @files ) {
        my $tar = Archive::Extract->new(
            'archive' => "$extlib_source/$_" );
        my $return = $tar->extract(
            'to' => $temp_dir );
        
        die "Error in build_extlibs: Failed to extract $_\n"
            if ( !$return );
        
        my $extract_dir = $tar->extract_path();
 
        chdir( $extract_dir )
            or die "Error in build_extlibs: Can't change"
                . " directory to $extract_dir: $!";

        my $makefile_args = "PREFIX=$prefix_dir LIB=$lib_dir";

        if ( -e "Makefile.PL" ) {
            system( "perl Makefile.PL $makefile_args" );
            sleep 1;
            system( 'make' );
            sleep 1;
            system( 'make install' );
        }
        else {
            die "Error in build_extlibs: Makefile.PL does"
                . " not exist in $extract_dir\n";
        }

        chdir( $cwd );
    }
}
